package com.bestcem.xm.user.service.impl;

import cn.hutool.core.lang.Dict;
import com.alibaba.excel.util.StringUtils;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.AuthErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.common.core.oss.enums.OssPathEnum;
import com.bestcem.xm.componet.filestorage.service.StorageService;
import com.bestcem.xm.user.service.OrganizationService;
import com.bestcem.xm.user.service.UserPrivateKeyBusinessService;
import com.bestcem.xm.user.service.UserPrivateKeyService;
import com.bestcem.xm.user.service.dto.user.OrganizationDTO;
import com.bestcem.xm.user.service.dto.user.UserPrivateKeyDTO;
import com.bestcem.xm.user.util.business.RsaUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;

/**
 * 公钥私钥业务服务
 *
 * @author qiongyu.cui <qiongyu.cui@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/25 11:31
 */
@Service
@Slf4j
public class UserPrivateKeyBusinessServiceImpl implements UserPrivateKeyBusinessService {

    @Resource
    private UserPrivateKeyService userPrivateKeyService;

    @Resource
    private OrganizationService organizationService;

    /*@Resource
    private OssService ossService;*/

    @Resource
    private StorageService storageService;

    //@Resource
    //private RsaGrpcService rsaGrpcService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult<Void> createOrgPrivateKeyInfo(String orgId) {
        // 参数校验
        if (StringUtils.isBlank(orgId)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "公司id不能为空！");
        }
        ServiceResult<OrganizationDTO> organization = organizationService.selectByPrimaryKey(orgId);
        if (Objects.isNull(organization.getData())) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未找到对应的公司信息！");
        }
        String oldPrivateKeyId = organization.getData().getPrivateKeyId();

        // 利用算法生成一对公钥私钥
        Map<String, String> rsaKeyMap;
        try {
            rsaKeyMap = RsaUtil.createRsaKey();
            //rsaKeyMap = rsaGrpcService.createRsaKeys();
        } catch (Exception e) {
            log.error("生成公钥私钥对失败：{0}", e.getCause());
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "生成公钥私钥对失败！");
        }
        String privateKey = RsaUtil.getPrivateKey(rsaKeyMap);
        String publicKey = RsaUtil.getPublicKey(rsaKeyMap);

        // 上传公钥文件信息
        /*String publicKeyFilePath = ossService.uploadFile(publicKey.getBytes(StandardCharsets.UTF_8),
                orgId + "_publicKey_file", OssPathEnum.USER, "_publicKey_file");*/
        String publicKeyFilePath = storageService.upload(publicKey.getBytes(StandardCharsets.UTF_8),
                orgId + "_publicKey_file", OssPathEnum.USER.getPath(), new Dict()).getUrl();
        // 创建公钥私钥信息
        UserPrivateKeyDTO privateKeyDTO = new UserPrivateKeyDTO();
        privateKeyDTO.setPem(privateKey);
        privateKeyDTO.setPublicKeyFilePath(publicKeyFilePath);
        ServiceResult<String> createPrivateRecord = userPrivateKeyService.insertSelective(privateKeyDTO);
        if (createPrivateRecord.isSuccess()) {
            String privateKeyId = createPrivateRecord.getData();
            // 开始更新公司的公钥私钥信息
            OrganizationDTO organizationDTO = new OrganizationDTO();
            organizationDTO.setOrgId(orgId);
            organizationDTO.setPrivateKeyId(privateKeyId);
            organizationDTO.setPublicKeyFilePath(publicKeyFilePath);
            ServiceResult<Boolean> organizationResult = organizationService.updateByPrimaryKeySelective(organizationDTO);
            if (organizationResult.isSuccess() && StringUtils.isNotBlank(oldPrivateKeyId)) {
                // 删除之前的公钥私钥记录，oss上的文件可以直接被同名覆盖
                userPrivateKeyService.deleteById(oldPrivateKeyId);
                return ServiceResult.success();
            }
        }
        return ServiceResult.fail("创建公司的公钥私钥失败！");
    }

    @Override
    public ServiceResult<String> decryptPassword(String orgId, String password) {
        // python引用：apps_mysql.user.util.utils.get_private_key_by_org_id
        if (StringUtils.isBlank(orgId) || StringUtils.isBlank(password)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "orgId或者password不能为空");
        }

        ServiceResult<OrganizationDTO> organization = organizationService.selectByPrimaryKey(orgId);
        if (!organization.isSuccess() || Objects.isNull(organization.getData())
                || StringUtils.isBlank(organization.getData().getPrivateKeyId())) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到对应的公司信息");
        }
        String privateKeyId = organization.getData().getPrivateKeyId();

        // 查询私钥信息
        ServiceResult<UserPrivateKeyDTO> userPrivateKey = userPrivateKeyService.selectById(privateKeyId);
        if (!userPrivateKey.isSuccess() || Objects.isNull(userPrivateKey.getData())) {
            return ServiceResult.fail(AuthErrorCodeEnum.PrivKeyNotFound, "未查询到私钥信息");
        }

        String pem = userPrivateKey.getData().getPem();
        String decrypt = RsaUtil.decrypt(pem, password);
        if (StringUtils.isBlank(decrypt)) {
            return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "解密失败");
        }

        return ServiceResult.success(decrypt);
    }

}
